package com.jprocms.module.cms.job;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jpro.framework.common.pojo.PageResult;
import com.jpro.framework.common.util.collection.CollectionUtils;
import com.jpro.framework.tenant.core.job.TenantJob;
import com.jpro.module.system.api.logger.OperateLogApi;
import com.jpro.module.system.api.logger.dto.OperateLogDelReqDTO;
import com.jpro.module.system.api.user.AdminUserApi;
import com.jprocms.module.cms.config.JproProperties;
import com.jprocms.module.cms.content.ContentEventPublisher;
import com.jprocms.module.cms.controller.admin.content.vo.ContentPageReqVO;
import com.jprocms.module.cms.convert.PageConverter;
import com.jprocms.module.cms.dal.dataobject.channel.ChannelDO;
import com.jprocms.module.cms.dal.dataobject.content.ContentCountDO;
import com.jprocms.module.cms.dal.dataobject.content.ContentDO;
import com.jprocms.module.cms.dal.dataobject.site.SiteDO;
import com.jprocms.module.cms.dal.mysql.content.ContentAttrMapper;
import com.jprocms.module.cms.dal.mysql.content.ContentCountMapper;
import com.jprocms.module.cms.dal.mysql.content.ContentExtMapper;
import com.jprocms.module.cms.dal.mysql.content.ContentMapper;
import com.jprocms.module.cms.dal.mysql.site.SiteMapper;
import com.jprocms.module.cms.dal.redis.RedisKeyConstants;
import com.jprocms.module.cms.dto.JobDto;
import com.jprocms.module.cms.enums.EnumIntCommonStatus;
import com.jprocms.module.cms.enums.EnumJobStatus;
import com.jprocms.module.cms.enums.EnumJobType;
import com.jprocms.module.cms.framework.cache.CacheService;
import com.jprocms.module.cms.service.accesslog.AccessService;
import com.jprocms.module.cms.service.channel.ChannelService;
import com.jprocms.module.cms.service.content.ContentAttrService;
import com.jprocms.module.cms.service.content.ContentCountService;
import com.jprocms.module.cms.service.globalconfig.GlobalConfigService;
import com.jprocms.module.cms.service.job.JobService;
import com.jprocms.module.cms.service.site.SiteService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.jprocms.module.cms.config.ThreadPoolConfiguration.CMS_COMMON_THREAD_POOL_TASK_EXECUTOR;
import static com.jprocms.module.cms.dal.redis.RedisKeyConstants.*;
import static com.jprocms.module.cms.web.Directives.getOrderItems;

@Slf4j
@Service
@DependsOn("scheduleUtil")
public class CmsSystemJobService implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        //xxl-job已经注册了数据 这里采用子线程是因为后续，后续启动顺序不一定是xxl-job先启动 避免因xxl-job未启动导致cms应用启动失败
        threadPoolTaskExecutor.execute(
                () -> {
                    try {
                        //添加内容刷新缓存数据入库的任务
                        JobDto sysJobDto = refreshContentViewsCacheToDb();
                        jobService.deleteByJobType(sysJobDto.getJobType());
                        jobService.addOrUpdateJob(sysJobDto);
                        //内容日访问统计
                        JobDto resetDayViewsJob = resetDayViewsJob();
                        jobService.deleteByJobType(resetDayViewsJob.getJobType());
                        jobService.addOrUpdateJob(resetDayViewsJob);
                        //年访问量统计
                        JobDto resetYearViewsJob = resetYearViewsJob();
                        jobService.deleteByJobType(resetYearViewsJob.getJobType());
                        jobService.addOrUpdateJob(resetYearViewsJob);

                        //删除实时预览的内容
                        JobDto deleteLivePreviewContentJob = deleteLivePreviewContentJob();
                        jobService.deleteByJobType(deleteLivePreviewContentJob.getJobType());
                        jobService.addOrUpdateJob(deleteLivePreviewContentJob);

                        //安全配置-长期未登录锁定账号定时检查
                        JobDto lockLongTimeNoLoginUserJob = lockLongTimeNoLoginUserJob();
                        jobService.deleteByJobType(lockLongTimeNoLoginUserJob.getJobType());
                        jobService.addOrUpdateJob(lockLongTimeNoLoginUserJob);

                        //流量统计任务
                        JobDto flowStatisticJob = flowStatisticJob();
                        jobService.deleteByJobType(flowStatisticJob.getJobType());
                        jobService.addOrUpdateJob(flowStatisticJob);

                        //操作日志清理（默认保留1年）
                        JobDto operateLogDelJob = opereateLogDelJob();
                        jobService.deleteByJobType(operateLogDelJob.getJobType());
                        jobService.addOrUpdateJob(operateLogDelJob);

                        //添加昨日站点访问量任务
                        JobDto siteYesterdayViews = refreshSiteYesterdayViewsJob();
                        jobService.deleteByJobType(siteYesterdayViews.getJobType());
                        jobService.addOrUpdateJob(siteYesterdayViews);
                    } catch (Exception e) {
                        log.error("cms相关任务注册失败", e);
                    }
                }
        );
    }

    private JobDto flowStatisticJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("flowStatisticJobHandler");
        jobDto.setJobName(EnumJobType.FLOW_STATISTIC.getName());
        jobDto.setJobType(EnumJobType.FLOW_STATISTIC.getCode());
        jobDto.setRemark(EnumJobType.FLOW_STATISTIC.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        // 更新访问统计信息。定时时间要比写入时间晚一些，以免数据未写入完成就开始统计。 每10分钟更新一次
        jobDto.setCron("55 1/10 * * * ? *");
        return jobDto;
    }

    /**
     * 流量统计任务
     */
    @TenantJob
    @XxlJob(value = "flowStatisticJobHandler")
    public void flowStatisticJobHandler() {
        log.info("流量统计任务开始");
        long start = System.currentTimeMillis();
        accessService.updateStat();
        accessService.deleteStatHistory();
        accessService.updateOnlineVisitors();
        long end = System.currentTimeMillis();
        log.info("流量统计任务结束,耗时{}", (end - start));
    }

    private JobDto deleteLivePreviewContentJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("deleteLivePreviewContentJobHandler");
        jobDto.setJobName(EnumJobType.DELETE_LIVE_PREVIEW_CONTENT.getName());
        jobDto.setJobType(EnumJobType.DELETE_LIVE_PREVIEW_CONTENT.getCode());
        jobDto.setRemark(EnumJobType.DELETE_LIVE_PREVIEW_CONTENT.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        // 秒 分钟 小时 每日22点执行
        jobDto.setCron("0 0 22 * * ? *");
        return jobDto;
    }

    private JobDto lockLongTimeNoLoginUserJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("lockLongTimeNoLoginUserJobHandler");
        jobDto.setJobName(EnumJobType.LOCK_LONGTIME_NOLOGIN_USER.getName());
        jobDto.setJobType(EnumJobType.LOCK_LONGTIME_NOLOGIN_USER.getCode());
        jobDto.setRemark(EnumJobType.LOCK_LONGTIME_NOLOGIN_USER.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        // 秒 分钟 小时 每日23点执行
        jobDto.setCron("20 22 7 * * ? *");
        return jobDto;
    }

    private JobDto refreshContentViewsCacheToDb() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("refreshContentViewsCacheToDbHandler");
        jobDto.setJobName(EnumJobType.CONTENT_VIEW_CACHE_REFRESH.getName());
        jobDto.setJobType(EnumJobType.CONTENT_VIEW_CACHE_REFRESH.getCode());
        jobDto.setRemark(EnumJobType.CONTENT_VIEW_CACHE_REFRESH.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        // 秒 分钟 小时
        jobDto.setCron("0 0/30 * * * ? *");
        return jobDto;
    }

    private JobDto refreshSiteYesterdayViewsJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("refreshSiteYesterdayViewsHandler");
        jobDto.setJobName(EnumJobType.YESTERDAY_SITE_VIEW_REFRESH.getName());
        jobDto.setJobType(EnumJobType.YESTERDAY_SITE_VIEW_REFRESH.getCode());
        jobDto.setRemark(EnumJobType.YESTERDAY_SITE_VIEW_REFRESH.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        // 秒 分钟 小时
        jobDto.setCron("0 59 23 * * ? *");
        return jobDto;
    }

    /**
     * 长期未登录锁定账号
     */
    @TenantJob
    @XxlJob(value = "lockLongTimeNoLoginUserJobHandler")
    public void lockLongTimeNoLoginUserJobHandler() {
        log.info("长期未登录锁定账号检查并锁定");
        long start = System.currentTimeMillis();

        adminUserApi.checkLongTimeNoLoginUser();
        long end = System.currentTimeMillis();
        log.info("长期未登录锁定账号检查并锁定,耗时{}", (end - start));
    }


    /**
     * 删除实时预览内容
     */
    @TenantJob
    @XxlJob(value = "deleteLivePreviewContentJobHandler")
    public void deleteLivePreviewContentJobHandler() {
        log.info("开始删除实时预览内容");
        long start = System.currentTimeMillis();

        ContentPageReqVO reqVO = new ContentPageReqVO();
        reqVO.setPageNo(1);
        reqVO.setPageSize(100);
        reqVO.setLivePreview(EnumIntCommonStatus.OPEN.getStatus());
        //默认回复时间降序，ID降序排序
        Collection<OrderItem> orderItems = getOrderItems(Arrays.asList("id_desc"));
        reqVO.setOrderItems(orderItems);
        doDeleteLivePreviewContent(reqVO);
        long end = System.currentTimeMillis();
        log.info("结束删除实时预览内容,耗时{}", (end - start));
    }

    private void doDeleteLivePreviewContent(ContentPageReqVO reqVO) {

        IPage<ContentDO> contentDOIPage = contentMapper.selectPage(reqVO, reqVO.getOrderItems(), new Page<>(reqVO.getPageNo(), reqVO.getPageSize()));
        PageResult<ContentDO> contentPage = pageConverter.page(contentDOIPage);
        //物理删除实时预览内容
        final List<Long> ids = CollectionUtils.convertList(contentPage.getList(), ContentDO::getId);
        ids.forEach(this::deleteContent);
        while (contentPage.getHasNext()) {
            reqVO.setPageNo(contentPage.getCurrent().intValue() + 1);
            doDeleteLivePreviewContent(reqVO);
        }
    }

    private void deleteContent(Long id) {
        // 删除
        contentMapper.deleteAbsoluteById(id);
        contentExtMapper.deleteAbsoluteById(id);
        contentCountMapper.deleteById(id);
        //刪除attr
        contentAttrService.deleteByContentId(id);
        //发送删除消息 触发es索引 静态页同步
        contentEventPublisher.sendContentDeleteEvent(Arrays.asList(id));
    }


    /**
     * 内容浏览计数刷新缓存入库
     */
    @TenantJob
    @XxlJob(value = "refreshContentViewsCacheToDbHandler")
    public void refreshContentViewsCacheToDbHandler() {

        doRefreshSiteViewsCacheToDb();
        doRefreshChannelViewsCacheToDb();
        doRefreshContentViewsCacheToDb();
    }

    /**
     * 站点昨日访问量更新
     */
    @TenantJob
    @XxlJob(value = "refreshSiteYesterdayViewsHandler")
    public void refreshSiteYesterdayViewsHandler() {
        doRefreshSiteYesterdayViews();
    }

    private JobDto resetDayViewsJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("resetDayViewsHandler");
        jobDto.setJobName(EnumJobType.DAY_VIEW_RESET.getName());
        jobDto.setJobType(EnumJobType.DAY_VIEW_RESET.getCode());
        jobDto.setRemark(EnumJobType.DAY_VIEW_RESET.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        //每日凌晨执行一次
        jobDto.setCron("0 0 0 ? * *  ");
        return jobDto;
    }

    private JobDto opereateLogDelJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("opereateLogDelHandler");
        jobDto.setJobName(EnumJobType.OPERATE_LOG_DEL.getName());
        jobDto.setJobType(EnumJobType.OPERATE_LOG_DEL.getCode());
        jobDto.setRemark(EnumJobType.OPERATE_LOG_DEL.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        //每日凌晨 25 执行一次
        jobDto.setCron("0 25 0 ? * *  ");
        return jobDto;
    }

    /**
     * 初始化栏目的日访问
     */
    @TenantJob
    @XxlJob(value = "resetDayViewsHandler")
    public void resetDayViewsHandler() {

        LambdaUpdateWrapper<ChannelDO> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(ChannelDO::getTodayViews, 0);
        channelService.update(new ChannelDO(), wrapper);

        UpdateWrapper<SiteDO> siteDOYesterDayUpdateWrapper = new UpdateWrapper<>();
        wrapper.setSql("yesterday_views=today_views");
        siteService.update(new SiteDO(), siteDOYesterDayUpdateWrapper);


        LambdaUpdateWrapper<SiteDO> siteDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        siteDOLambdaUpdateWrapper.set(SiteDO::getTodayViews, 0);
        siteService.update(new SiteDO(), siteDOLambdaUpdateWrapper);

        //并且清空对应redis缓存
        cacheService.deleteObject(CHANNEL_DAY_VIEW);
        cacheService.deleteObject(SITE_DAY_VIEW);
    }

    private JobDto resetYearViewsJob() {
        JobDto jobDto = new JobDto();
        jobDto.setJobHandler("resetYearViewsHandler");
        jobDto.setJobName(EnumJobType.YEAR_VIEW_RESET.getName());
        jobDto.setJobType(EnumJobType.YEAR_VIEW_RESET.getCode());
        jobDto.setRemark(EnumJobType.YEAR_VIEW_RESET.getName());
        jobDto.setParams("");
        jobDto.setDataId(null);
        jobDto.setStatus(EnumJobStatus.RUNABLE.getCode());
        //每年1月1日凌晨执行一次
        jobDto.setCron("0 0 0 1 1 ?");
        return jobDto;
    }

    /**
     * 处理站点和栏目的年统计数据
     */
    @TenantJob
    @XxlJob(value = "resetYearViewsHandler")
    public void resetYearViewsHandler() {

        LambdaUpdateWrapper<ChannelDO> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(ChannelDO::getYearViews, 0);
        channelService.update(new ChannelDO(), wrapper);
        LambdaUpdateWrapper<SiteDO> siteDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        siteDOLambdaUpdateWrapper.set(SiteDO::getYearViews, 0);
        siteService.update(new SiteDO(), siteDOLambdaUpdateWrapper);
        //并且清空对应redis缓存
        cacheService.deleteObject(CHANNEL_YEAR_VIEW);
        cacheService.deleteObject(SITE_YEAR_VIEW);
    }

    @TenantJob
    @XxlJob(value = "opereateLogDelHandler")
    public void opereateLogDelHandler() {

        //暂定保留1年的操作日志
        OperateLogDelReqDTO logDelReqDTO = new OperateLogDelReqDTO();
        logDelReqDTO.setDays(jproProperties.getOperateLogSaveDays());
        operateLogApi.deleteDaysBefore(logDelReqDTO);
    }

    private void doRefreshContentViewsCacheToDb() {
        log.info("内容浏览计数刷新缓存入库开始");
        Map<String, Object> contentCacheMap = cacheService.getCacheMap(RedisKeyConstants.CONTENT_VIEW);
        if (CollUtil.isNotEmpty(contentCacheMap)) {
            Set<Map.Entry<String, Object>> entries = contentCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long contentId = Long.parseLong(entry.getKey());
                Integer views = (Integer) entry.getValue();
                LambdaUpdateWrapper<ContentCountDO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(ContentCountDO::getViews, views);
                updateWrapper.eq(ContentCountDO::getId, contentId);
                contentCountService.update(new ContentCountDO(), updateWrapper);
            }
            log.info("内容浏览计数刷新缓存入库结束,处理内容数{}", entries.size());
            contentCacheMap.clear();
            cacheService.setCacheMap(RedisKeyConstants.CONTENT_VIEW, contentCacheMap);
        }
    }

    private void doRefreshChannelViewsCacheToDb() {
        log.info("栏目浏览计数刷新缓存入库开始");
        Map<String, Object> channelCacheMap = cacheService.getCacheMap(RedisKeyConstants.CHANNEL_VIEW);
        if (CollUtil.isNotEmpty(channelCacheMap)) {
            Set<Map.Entry<String, Object>> entries = channelCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long channelId = Long.parseLong(entry.getKey());
                Long views = Long.parseLong(entry.getValue().toString());
                LambdaUpdateWrapper<ChannelDO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(ChannelDO::getViews, views);
                updateWrapper.eq(ChannelDO::getId, channelId);
                channelService.update(new ChannelDO(), updateWrapper);
            }
            channelCacheMap.clear();
            cacheService.setCacheMap(RedisKeyConstants.CHANNEL_VIEW, channelCacheMap);
        }

        Map<String, Object> channelDayCacheMap = cacheService.getCacheMap(CHANNEL_DAY_VIEW);
        if (CollUtil.isNotEmpty(channelDayCacheMap)) {
            Set<Map.Entry<String, Object>> entries = channelDayCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long channelId = Long.parseLong(entry.getKey());
                Integer dayViews = Integer.parseInt(entry.getValue().toString());
                LambdaUpdateWrapper<ChannelDO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(ChannelDO::getTodayViews, dayViews);
                updateWrapper.eq(ChannelDO::getId, channelId);
                channelService.update(new ChannelDO(), updateWrapper);
            }
            channelDayCacheMap.clear();
            cacheService.setCacheMap(CHANNEL_DAY_VIEW, channelDayCacheMap);
        }

        Map<String, Object> channelYearCacheMap = cacheService.getCacheMap(RedisKeyConstants.CHANNEL_YEAR_VIEW);
        if (CollUtil.isNotEmpty(channelYearCacheMap)) {
            Set<Map.Entry<String, Object>> entries = channelYearCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long channelId = Long.parseLong(entry.getKey());
                Long yearViews = Long.parseLong(entry.getValue().toString());
                LambdaUpdateWrapper<ChannelDO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(ChannelDO::getYearViews, yearViews);
                updateWrapper.eq(ChannelDO::getId, channelId);
                channelService.update(new ChannelDO(), updateWrapper);
            }
            channelYearCacheMap.clear();
            cacheService.setCacheMap(RedisKeyConstants.CHANNEL_YEAR_VIEW, channelYearCacheMap);
        }

        log.info("栏目浏览计数刷新缓存入库结束");
    }

    private void doRefreshSiteViewsCacheToDb() {
        log.info("站点浏览计数刷新缓存入库开始");
        Map<String, Object> siteViewCacheMap = cacheService.getCacheMap(RedisKeyConstants.SITE_VIEW);
        if (CollUtil.isNotEmpty(siteViewCacheMap)) {
            Set<Map.Entry<String, Object>> entries = siteViewCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long siteId = Long.parseLong(entry.getKey());
                SiteDO siteDO = siteService.getSite(siteId);
                Long views = siteDO.getViews();
                if (entry.getValue() instanceof Integer) {
                    views = ((Integer) entry.getValue()).longValue();
                } else if (entry.getValue() instanceof Long) {
                    views = (Long) entry.getValue();
                }
                LambdaUpdateWrapper<SiteDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lambdaUpdateWrapper.set(SiteDO::getViews, views);
                lambdaUpdateWrapper.eq(SiteDO::getId, siteId);
                siteMapper.update(new SiteDO(), lambdaUpdateWrapper);
            }
        }

        Map<String, Object> siteYearCacheMap = cacheService.getCacheMap(RedisKeyConstants.SITE_YEAR_VIEW);
        if (CollUtil.isNotEmpty(siteYearCacheMap)) {
            Set<Map.Entry<String, Object>> entries = siteYearCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long siteId = Long.parseLong(entry.getKey());
                SiteDO siteDO = siteService.getSite(siteId);
                Long yearViews = siteDO.getYearViews();
                if (entry.getValue() instanceof Integer) {
                    yearViews = ((Integer) entry.getValue()).longValue();
                } else if (entry.getValue() instanceof Long) {
                    yearViews = (Long) entry.getValue();
                }
                LambdaUpdateWrapper<SiteDO> siteDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                siteDOLambdaUpdateWrapper.set(SiteDO::getYearViews, yearViews);
                siteDOLambdaUpdateWrapper.eq(SiteDO::getId, siteId);
                siteMapper.update(new SiteDO(), siteDOLambdaUpdateWrapper);
            }
        }

        Map<String, Object> siteDayViewCacheMap = cacheService.getCacheMap(RedisKeyConstants.SITE_DAY_VIEW);
        if (CollUtil.isNotEmpty(siteDayViewCacheMap)) {
            Set<Map.Entry<String, Object>> entries = siteDayViewCacheMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Long siteId = Long.parseLong(entry.getKey());
                Integer dayViews = (Integer) entry.getValue();
                LambdaUpdateWrapper<SiteDO> siteDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                siteDOLambdaUpdateWrapper.set(SiteDO::getTodayViews, dayViews);
                siteDOLambdaUpdateWrapper.eq(SiteDO::getId, siteId);
                siteMapper.update(new SiteDO(), siteDOLambdaUpdateWrapper);
            }
        }
        log.info("站点浏览计数刷新缓存入库结束");
    }

    /**
     * 每日最后时刻更新昨日访问量为今日的访问量
     */
    private void doRefreshSiteYesterdayViews() {
        log.info("站点浏览计数昨日数量开始");
        final List<SiteDO> siteDOS = siteMapper.selectList();
        if (CollUtil.isNotEmpty(siteDOS)) {
            for (SiteDO siteDO: siteDOS) {
                Long siteId = siteDO.getId();
                LambdaUpdateWrapper<SiteDO> siteDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                siteDOLambdaUpdateWrapper.set(SiteDO::getYesterdayViews, siteDO.getTodayViews());
                siteDOLambdaUpdateWrapper.eq(SiteDO::getId, siteId);
                siteMapper.update(new SiteDO(), siteDOLambdaUpdateWrapper);
            }
        }
        log.info("站点浏览计数昨日数量结束");
    }

    @Resource(name = CMS_COMMON_THREAD_POOL_TASK_EXECUTOR)
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private ContentMapper contentMapper;
    @Resource
    private JobService jobService;
    @Resource
    private ContentCountService contentCountService;
    @Resource
    private ChannelService channelService;
    @Resource
    private SiteService siteService;
    @Resource
    private CacheService cacheService;
    @Resource
    private PageConverter pageConverter;
    @Resource
    private ContentAttrMapper contentAttrMapper;
    @Resource
    private ContentExtMapper contentExtMapper;
    @Resource
    private ContentCountMapper contentCountMapper;
    @Resource
    private ContentAttrService contentAttrService;
    @Resource
    private ContentEventPublisher contentEventPublisher;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private GlobalConfigService globalConfigService;
    @Resource
    private SiteMapper siteMapper;
    @Resource
    private AccessService accessService;
    @Resource
    private OperateLogApi operateLogApi;
    @Resource
    private JproProperties jproProperties;

    @Override
    public void destroy() throws Exception {
        try {
            //删除内容刷新缓存数据入库的任务
            JobDto sysJobDto = refreshContentViewsCacheToDb();
            jobService.deleteByJobType(sysJobDto.getJobType());
            //内容日访问统计
            JobDto resetDayViewsJob = resetDayViewsJob();
            jobService.deleteByJobType(resetDayViewsJob.getJobType());
            //年访问量统计
            JobDto resetYearViewsJob = resetYearViewsJob();
            jobService.deleteByJobType(resetYearViewsJob.getJobType());
            //删除实时预览的内容
            JobDto deleteLivePreviewContentJob = deleteLivePreviewContentJob();
            jobService.deleteByJobType(deleteLivePreviewContentJob.getJobType());
            //安全配置-长期未登录锁定账号定时检查
            JobDto lockLongTimeNoLoginUserJob = lockLongTimeNoLoginUserJob();
            jobService.deleteByJobType(lockLongTimeNoLoginUserJob.getJobType());
            //流量统计任务
            JobDto flowStatisticJob = flowStatisticJob();
            jobService.deleteByJobType(flowStatisticJob.getJobType());
            //操作日志清理（默认保留1年）
            JobDto operateLogDelJob = opereateLogDelJob();
            jobService.deleteByJobType(operateLogDelJob.getJobType());
            //添加昨日站点访问量任务
            JobDto siteYesterdayViews = refreshSiteYesterdayViewsJob();
            jobService.deleteByJobType(siteYesterdayViews.getJobType());
        } catch (Exception e) {
            log.error("cms删除任务失败", e);
        }
    }
}
